home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Jumpstart / Multimedia Microsoft Jumpstart Version 1.1a (Microsoft).BIN / develpmt / source / palfx / dib.c next >
Encoding:
C/C++ Source or Header  |  1992-09-20  |  39.1 KB  |  1,628 lines

  1. /*----------------------------------------------------------------------------*\
  2. |   Routines for dealing with Device independent bitmaps                       |
  3. |                                           |
  4. \*----------------------------------------------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include "gmem.h"
  8. #include "dib.h"
  9.  
  10. HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal);
  11.  
  12. //DWORD NEAR PASCAL lread(int fh, VOID FAR *pv, DWORD ul);
  13. //DWORD NEAR PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul);
  14.  
  15. /* flags for _lseek */
  16. #define  SEEK_CUR 1
  17. #define  SEEK_END 2
  18. #define  SEEK_SET 0
  19.  
  20. /*
  21.  *   Open a DIB file and return a MEMORY DIB, a memory handle containing..
  22.  *
  23.  *   BITMAP INFO    bi
  24.  *   palette data
  25.  *   bits....
  26.  *
  27.  */
  28. HANDLE OpenDIB(LPSTR szFile)
  29. {
  30.     unsigned            fh;
  31.     BITMAPINFOHEADER    bi;
  32.     LPBITMAPINFOHEADER  lpbi;
  33.     DWORD               dwLen;
  34.     DWORD               dwBits;
  35.     HANDLE              hdib;
  36.     HANDLE              h;
  37.     OFSTRUCT            of;
  38.  
  39.     if (HIWORD((DWORD)szFile) == 0)
  40.     {
  41.         fh = LOWORD((DWORD)szFile);
  42.     }
  43.     else
  44.     {
  45.         fh = OpenFile(szFile, &of, OF_READ);
  46.     }
  47.  
  48.     if (fh == -1)
  49.         return NULL;
  50.  
  51.     hdib = ReadDibBitmapInfo(fh);
  52.  
  53.     if (!hdib)
  54.         return NULL;
  55.  
  56.     DibInfo(hdib,&bi);
  57.  
  58.     /* How much memory do we need to hold the DIB */
  59.  
  60.     dwBits = bi.biSizeImage;
  61.     dwLen  = bi.biSize + PaletteSize(&bi) + dwBits;
  62.  
  63.     /* Can we get more memory? */
  64.  
  65.     h = GReAlloc(hdib,dwLen);
  66.  
  67.     if (!h)
  68.     {
  69.         GFree(hdib);
  70.         hdib = NULL;
  71.     }
  72.     else
  73.     {
  74.         hdib = h;
  75.     }
  76.  
  77.     if (hdib)
  78.     {
  79.         lpbi = GLock(hdib);
  80.  
  81.         /* read in the bits */
  82.         _hread(fh, (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi), dwBits);
  83.  
  84.         GUnlock(hdib);
  85.     }
  86.  
  87.  
  88.     if (HIWORD((DWORD)szFile) != 0)
  89.         _lclose(fh);
  90.  
  91.     return hdib;
  92. }
  93.  
  94. /*
  95.  *   Write a global handle in CF_DIB format to a file.
  96.  *
  97.  */
  98. BOOL WriteDIB(LPSTR szFile,HANDLE hdib)
  99. {
  100.     BITMAPFILEHEADER    hdr;
  101.     LPBITMAPINFOHEADER  lpbi;
  102.     BITMAPINFOHEADER    bi;
  103.     int                 fh;
  104.     OFSTRUCT            of;
  105.     DWORD               dwSize;
  106.  
  107.     if (!hdib)
  108.         return FALSE;
  109.  
  110.     if (HIWORD((DWORD)szFile) == 0)
  111.     {
  112.         fh = LOWORD((DWORD)szFile);
  113.     }
  114.     else
  115.     {
  116.         fh = OpenFile(szFile,&of,OF_CREATE|OF_READWRITE);
  117.     }
  118.  
  119.     if (fh == -1)
  120.         return FALSE;
  121.  
  122.     DibInfo(hdib,&bi);
  123.  
  124.     dwSize = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  125.  
  126.     lpbi = GLock(hdib);
  127.  
  128.     hdr.bfType          = BFT_BITMAP;
  129.     hdr.bfSize          = dwSize + sizeof(BITMAPFILEHEADER);
  130.     hdr.bfReserved1     = 0;
  131.     hdr.bfReserved2     = 0;
  132.     hdr.bfOffBits       = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize +
  133.                           PaletteSize(lpbi);
  134.  
  135.     _hwrite(fh, (LPVOID)&hdr, sizeof(BITMAPFILEHEADER));
  136.     _hwrite(fh, (LPVOID)lpbi, dwSize);
  137.  
  138.     GUnlock(hdib);
  139.  
  140.     if (HIWORD((DWORD)szFile) != 0)
  141.         _lclose(fh);
  142.  
  143.     return TRUE;
  144. }
  145.  
  146. /*
  147.  *  DibInfo(hbi, lpbi)
  148.  *
  149.  *  retrives the DIB info associated with a CF_DIB format memory block.
  150.  */
  151. BOOL DibInfo(HANDLE hbi,LPBITMAPINFOHEADER lpbi)
  152. {
  153.     if (hbi)
  154.     {
  155.         *lpbi = *(LPBITMAPINFOHEADER)GLock(hbi);
  156.         GUnlock(hbi);
  157.  
  158.         if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  159.         {
  160.             BITMAPCOREHEADER bc;
  161.  
  162.             bc = *(LPBITMAPCOREHEADER)lpbi;
  163.  
  164.             lpbi->biSize               = sizeof(BITMAPINFOHEADER);
  165.             lpbi->biWidth              = (DWORD)bc.bcWidth;
  166.             lpbi->biHeight             = (DWORD)bc.bcHeight;
  167.             lpbi->biPlanes             =  (WORD)bc.bcPlanes;
  168.             lpbi->biBitCount           =  (WORD)bc.bcBitCount;
  169.             lpbi->biCompression        = BI_RGB;
  170.             lpbi->biSizeImage          = 0;
  171.             lpbi->biXPelsPerMeter      = 0;
  172.             lpbi->biYPelsPerMeter      = 0;
  173.             lpbi->biClrUsed            = 0;
  174.             lpbi->biClrImportant       = 0;
  175.         }
  176.  
  177.         /*
  178.          * fill in the default fields
  179.          */
  180.         if (lpbi->biSizeImage == 0L)
  181.             lpbi->biSizeImage = lpbi->biHeight * DIBWIDTHBYTES(*lpbi);
  182.  
  183.         if (lpbi->biClrUsed == 0L)
  184.             lpbi->biClrUsed = DibNumColors(lpbi);
  185.  
  186.         return TRUE;
  187.     }
  188.     return FALSE;
  189. }
  190.  
  191. /*
  192.  *  CreateBIPalette()
  193.  *
  194.  *  Given a Pointer to a BITMAPINFO struct will create a
  195.  *  a GDI palette object from the color table.
  196.  *
  197.  *  works with "old" and "new" DIB's
  198.  *
  199.  */
  200. HPALETTE CreateBIPalette(LPBITMAPINFOHEADER lpbi)
  201. {
  202.     LOGPALETTE          *pPal;
  203.     HPALETTE            hpal = NULL;
  204.     WORD                nNumColors;
  205.     WORD                i;
  206.     RGBQUAD        FAR *pRgb;
  207.     BOOL                fCoreHeader;
  208.  
  209.     if (!lpbi)
  210.         return NULL;
  211.  
  212.     fCoreHeader = (lpbi->biSize == sizeof(BITMAPCOREHEADER));
  213.  
  214.     pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  215.     nNumColors = DibNumColors(lpbi);
  216.  
  217.     if (nNumColors)
  218.     {
  219.         pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  220.  
  221.         if (!pPal)
  222.             goto exit;
  223.  
  224.         pPal->palNumEntries = nNumColors;
  225.         pPal->palVersion    = PALVERSION;
  226.  
  227.         for (i = 0; i < nNumColors; i++)
  228.         {
  229.             pPal->palPalEntry[i].peRed   = pRgb->rgbRed;
  230.             pPal->palPalEntry[i].peGreen = pRgb->rgbGreen;
  231.             pPal->palPalEntry[i].peBlue  = pRgb->rgbBlue;
  232.             pPal->palPalEntry[i].peFlags = (BYTE)0;
  233.  
  234.             if (fCoreHeader)
  235.                 ((LPSTR)pRgb) += sizeof(RGBTRIPLE) ;
  236.             else
  237.                 pRgb++;
  238.         }
  239.  
  240.         hpal = CreatePalette(pPal);
  241.         LocalFree((HANDLE)pPal);
  242.     }
  243.     else if (lpbi->biBitCount == 24)
  244.     {
  245.         hpal = CreateColorPalette();
  246.     }
  247.  
  248. exit:
  249.     return hpal;
  250. }
  251.  
  252.  
  253. /*
  254.  *  CreateDibPalette()
  255.  *
  256.  *  Given a Global HANDLE to a BITMAPINFO Struct
  257.  *  will create a GDI palette object from the color table.
  258.  *
  259.  *  works with "old" and "new" DIB's
  260.  *
  261.  */
  262. HPALETTE CreateDibPalette(HANDLE hbi)
  263. {
  264.     HPALETTE hpal;
  265.  
  266.     if (!hbi)
  267.         return NULL;
  268.  
  269.     hpal = CreateBIPalette((LPBITMAPINFOHEADER)GLock(hbi));
  270.     GUnlock(hbi);
  271.     return hpal;
  272. }
  273.  
  274. //
  275. // create a 6*6*6 rainbow palette
  276. //
  277. HPALETTE CreateColorPalette()
  278. {
  279.     LOGPALETTE          *pPal;
  280.     PALETTEENTRY        *ppe;
  281.     HPALETTE            hpal = NULL;
  282.     WORD                nNumColors;
  283.     BYTE                r,g,b;
  284.  
  285.     nNumColors = 6*6*6;
  286.     pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  287.  
  288.     if (!pPal)
  289.     goto exit;
  290.  
  291.     pPal->palNumEntries = nNumColors;
  292.     pPal->palVersion    = PALVERSION;
  293.  
  294.     ppe = pPal->palPalEntry;
  295.  
  296.     for (r=0; r<6; r++)
  297.         for (g=0; g<6; g++)
  298.             for (b=0; b<6; b++)
  299.             {
  300.                 ppe->peRed   = (BYTE)((WORD)r * 255 / 6);
  301.                 ppe->peGreen = (BYTE)((WORD)g * 255 / 6);
  302.                 ppe->peBlue  = (BYTE)((WORD)b * 255 / 6);
  303.                 ppe->peFlags = (BYTE)0;
  304.                 ppe++;
  305.             }
  306.  
  307.     hpal = CreatePalette(pPal);
  308.     LocalFree((HANDLE)pPal);
  309.  
  310. exit:
  311.     return hpal;
  312. }
  313.  
  314. /* CreateSystemPalette()
  315.  *
  316.  * Return a palette which represents the system (physical) palette.
  317.  * By selecting this palette into a screen DC and realizing the palette,
  318.  * the exact physical mapping will be restored
  319.  *
  320.  * one use for this is when "snaping" the screen as a bitmap
  321.  *
  322.  * On error (e.g. out of memory), NULL is returned.
  323.  */
  324. HPALETTE CreateSystemPalette()
  325. {
  326.     HDC             hdc;                    // DC onto the screen
  327.     int             iSizePalette;           // size of entire palette
  328.     int             iFixedPalette;          // number of reserved colors
  329.     NPLOGPALETTE    pLogPal = NULL;
  330.     HPALETTE        hpal = NULL;
  331.     int             i;
  332.  
  333.     hdc = GetDC(NULL);
  334.  
  335.     iSizePalette = GetDeviceCaps(hdc, SIZEPALETTE);
  336.  
  337.     //
  338.     // determine the number of 'static' system colors that
  339.     // are currently reserved
  340.     //
  341.     if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC)
  342.         iFixedPalette = GetDeviceCaps(hdc, NUMCOLORS);
  343.     else
  344.         iFixedPalette = 2;
  345.  
  346.     //
  347.     // create a logical palette containing the system colors;
  348.     // this palette has all entries except fixed (system) colors
  349.     // flagged as PC_NOCOLLAPSE
  350.     //
  351.     pLogPal = (NPLOGPALETTE)LocalAlloc(LPTR, sizeof(LOGPALETTE)
  352.             + iSizePalette * sizeof(PALETTEENTRY));
  353.  
  354.     if (pLogPal)
  355.     {
  356.         pLogPal->palVersion = 0x300;
  357.         pLogPal->palNumEntries = iSizePalette;
  358.  
  359.         GetSystemPaletteEntries(hdc, 0, iSizePalette, pLogPal->palPalEntry);
  360.  
  361.         for (i = iFixedPalette/2; i < iSizePalette-iFixedPalette/2; i++)
  362.             pLogPal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
  363.  
  364.         hpal = CreatePalette(pLogPal);
  365.     LocalFree((HANDLE)pLogPal);
  366.     }
  367.  
  368.     ReleaseDC(NULL,hdc);
  369.     return hpal;
  370. }
  371.  
  372.  
  373.  
  374.  
  375. /*
  376.  *  ReadDibBitmapInfo()
  377.  *
  378.  *  Will read a file in DIB format and return a global HANDLE to it's
  379.  *  BITMAPINFO.  This function will work with both "old" and "new"
  380.  *  bitmap formats, but will allways return a "new" BITMAPINFO
  381.  *
  382.  */
  383. HANDLE ReadDibBitmapInfo(int fh)
  384. {
  385.     DWORD     off;
  386.     HANDLE    hbi = NULL;
  387.     int       size;
  388.     int       i;
  389.     WORD      nNumColors;
  390.  
  391.     RGBQUAD FAR       *pRgb;
  392.     BITMAPINFOHEADER   bi;
  393.     BITMAPCOREHEADER   bc;
  394.     LPBITMAPINFOHEADER lpbi;
  395.     BITMAPFILEHEADER   bf;
  396.  
  397.     if (fh == -1)
  398.         return NULL;
  399.  
  400.     off = _llseek(fh,0L,SEEK_CUR);
  401.  
  402.     if (sizeof(bf) != _lread(fh,(LPSTR)&bf,sizeof(bf)))
  403.         return FALSE;
  404.  
  405.     /*
  406.      *  do we have a RC HEADER?
  407.      */
  408.     if (!ISDIB(bf.bfType))
  409.     {
  410.         bf.bfOffBits = 0L;
  411.         _llseek(fh,off,SEEK_SET);
  412.     }
  413.  
  414.     if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
  415.         return FALSE;
  416.  
  417.     nNumColors = DibNumColors(&bi);
  418.  
  419.     /*
  420.      *  what type of bitmap info is this?
  421.      */
  422.     switch (size = (int)bi.biSize)
  423.     {
  424.         case sizeof(BITMAPINFOHEADER):
  425.             break;
  426.  
  427.         case sizeof(BITMAPCOREHEADER):
  428.             bc = *(LPBITMAPCOREHEADER)&bi;
  429.             bi.biSize               = sizeof(BITMAPINFOHEADER);
  430.             bi.biWidth              = (DWORD)bc.bcWidth;
  431.             bi.biHeight             = (DWORD)bc.bcHeight;
  432.             bi.biPlanes             =  (WORD)bc.bcPlanes;
  433.             bi.biBitCount           =  (WORD)bc.bcBitCount;
  434.             bi.biCompression        = BI_RGB;
  435.             bi.biSizeImage          = 0;
  436.             bi.biXPelsPerMeter      = 0;
  437.             bi.biYPelsPerMeter      = 0;
  438.             bi.biClrUsed            = nNumColors;
  439.             bi.biClrImportant       = nNumColors;
  440.  
  441.             _llseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
  442.  
  443.             break;
  444.  
  445.         default:
  446.             return NULL;       /* not a DIB */
  447.     }
  448.  
  449.     /*
  450.      *    fill in some default values!
  451.      */
  452.     if (bi.biSizeImage == 0)
  453.     {
  454.         bi.biSizeImage = bi.biHeight * DIBWIDTHBYTES(bi);
  455.  
  456.     }
  457.  
  458.     if (bi.biXPelsPerMeter == 0)
  459.     {
  460.         bi.biXPelsPerMeter = 0;         // ??????????????
  461.     }
  462.  
  463.     if (bi.biYPelsPerMeter == 0)
  464.     {
  465.         bi.biYPelsPerMeter = 0;         // ??????????????
  466.     }
  467.  
  468.     if (bi.biClrUsed == 0)
  469.     {
  470.         bi.biClrUsed = DibNumColors(&bi);
  471.     }
  472.  
  473.     hbi = GAlloc((LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
  474.     if (!hbi)
  475.         return NULL;
  476.  
  477.     lpbi = (VOID FAR *)GLock(hbi);
  478.     *lpbi = bi;
  479.  
  480.     pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + bi.biSize);
  481.  
  482.     if (nNumColors)
  483.     {
  484.         if (size == sizeof(BITMAPCOREHEADER))
  485.         {
  486.             /*
  487.              * convert a old color table (3 byte entries) to a new
  488.              * color table (4 byte entries)
  489.              */
  490.             _lread(fh,(LPSTR)pRgb,nNumColors * sizeof(RGBTRIPLE));
  491.  
  492.             for (i=nNumColors-1; i>=0; i--)
  493.             {
  494.                 RGBQUAD rgb;
  495.  
  496.                 rgb.rgbRed      = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
  497.                 rgb.rgbBlue     = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
  498.                 rgb.rgbGreen    = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
  499.                 rgb.rgbReserved = (BYTE)0;
  500.  
  501.                 pRgb[i] = rgb;
  502.             }
  503.         }
  504.         else
  505.         {
  506.             _lread(fh,(LPSTR)pRgb,nNumColors * sizeof(RGBQUAD));
  507.         }
  508.     }
  509.  
  510.     if (bf.bfOffBits != 0L)
  511.         _llseek(fh,off + bf.bfOffBits,SEEK_SET);
  512.  
  513.     GUnlock(hbi);
  514.     return hbi;
  515. }
  516.  
  517. /*  How big is the palette? if bits per pel not 24
  518.  *  no of bytes to read is 6 for 1 bit, 48 for 4 bits
  519.  *  256*3 for 8 bits and 0 for 24 bits
  520.  */
  521. WORD PaletteSize(VOID FAR * pv)
  522. {
  523.     #define lpbi ((LPBITMAPINFOHEADER)pv)
  524.     #define lpbc ((LPBITMAPCOREHEADER)pv)
  525.  
  526.     WORD    NumColors;
  527.  
  528.     NumColors = DibNumColors(lpbi);
  529.  
  530.     if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  531.         return NumColors * sizeof(RGBTRIPLE);
  532.     else
  533.         return NumColors * sizeof(RGBQUAD);
  534.  
  535.     #undef lpbi
  536.     #undef lpbc
  537. }
  538.  
  539. /*  How Many colors does this DIB have?
  540.  *  this will work on both PM and Windows bitmap info structures.
  541.  */
  542. WORD DibNumColors(VOID FAR * pv)
  543. {
  544.     #define lpbi ((LPBITMAPINFOHEADER)pv)
  545.     #define lpbc ((LPBITMAPCOREHEADER)pv)
  546.  
  547.     int bits;
  548.  
  549.     /*
  550.      *  with the new format headers, the size of the palette is in biClrUsed
  551.      *  else is dependent on bits per pixel
  552.      */
  553.     if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
  554.     {
  555.         if (lpbi->biClrUsed != 0)
  556.             return (WORD)lpbi->biClrUsed;
  557.  
  558.         bits = lpbi->biBitCount;
  559.     }
  560.     else
  561.     {
  562.         bits = lpbc->bcBitCount;
  563.     }
  564.  
  565.     switch (bits)
  566.     {
  567.     case 1:
  568.             return 2;
  569.     case 4:
  570.             return 16;
  571.     case 8:
  572.             return 256;
  573.     default:
  574.             return 0;
  575.     }
  576.  
  577.     #undef lpbi
  578.     #undef lpbc
  579. }
  580.  
  581. /*
  582.  *  DibFromBitmap()
  583.  *
  584.  *  Will create a global memory block in DIB format that represents the DDB
  585.  *  passed in
  586.  *
  587.  */
  588. HANDLE DibFromBitmap(HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal, WORD wUsage)
  589. {
  590.     BITMAP               bm;
  591.     BITMAPINFOHEADER     bi;
  592.     BITMAPINFOHEADER FAR *lpbi;
  593.     DWORD                dwLen;
  594.     int                  nColors;
  595.     HANDLE               hdib;
  596.     HANDLE               h;
  597.     HDC                  hdc;
  598.  
  599.     if (wUsage == 0)
  600.         wUsage = DIB_RGB_COLORS;
  601.  
  602.     if (!hbm)
  603.         return NULL;
  604.  
  605.     if (biStyle == BI_RGB && wUsage == DIB_RGB_COLORS)
  606.         return CreateLogicalDib(hbm,biBits,hpal);
  607.  
  608.     if (hpal == NULL)
  609.         hpal = GetStockObject(DEFAULT_PALETTE);
  610.  
  611.     GetObject(hbm,sizeof(bm),(LPSTR)&bm);
  612.     GetObject(hpal,sizeof(nColors),(LPSTR)&nColors);
  613.  
  614.     if (biBits == 0)
  615.         biBits = bm.bmPlanes * bm.bmBitsPixel;
  616.  
  617.     bi.biSize               = sizeof(BITMAPINFOHEADER);
  618.     bi.biWidth              = bm.bmWidth;
  619.     bi.biHeight             = bm.bmHeight;
  620.     bi.biPlanes             = 1;
  621.     bi.biBitCount           = biBits;
  622.     bi.biCompression        = biStyle;
  623.     bi.biSizeImage          = 0;
  624.     bi.biXPelsPerMeter      = 0;
  625.     bi.biYPelsPerMeter      = 0;
  626.     bi.biClrUsed            = 0;
  627.     bi.biClrImportant       = 0;
  628.  
  629.     dwLen  = bi.biSize + PaletteSize(&bi);
  630.  
  631.     hdc = CreateCompatibleDC(NULL);
  632.     hpal = SelectPalette(hdc,hpal,FALSE);
  633.     RealizePalette(hdc);  // why is this needed on a MEMORY DC? GDI bug??
  634.  
  635.     hdib = GAlloc(dwLen);
  636.  
  637.     if (!hdib)
  638.         goto exit;
  639.  
  640.     lpbi = GLock(hdib);
  641.  
  642.     *lpbi = bi;
  643.  
  644.     /*
  645.      *  call GetDIBits with a NULL lpBits param, so it will calculate the
  646.      *  biSizeImage field for us
  647.      */
  648.     GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
  649.         NULL, (LPBITMAPINFO)lpbi, wUsage);
  650.  
  651.     bi = *lpbi;
  652.     GUnlock(hdib);
  653.  
  654.     /*
  655.      * HACK! if the driver did not fill in the biSizeImage field, make one up
  656.      */
  657.     if (bi.biSizeImage == 0)
  658.     {
  659.         bi.biSizeImage = (DWORD)WIDTHBYTES(bm.bmWidth * biBits) * bm.bmHeight;
  660.  
  661.         if (biStyle != BI_RGB)
  662.             bi.biSizeImage = (bi.biSizeImage * 3) / 2;
  663.     }
  664.  
  665.     /*
  666.      *  realloc the buffer big enough to hold all the bits
  667.      */
  668.     dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  669.     if (h = GReAlloc(hdib,dwLen))
  670.     {
  671.         hdib = h;
  672.     }
  673.     else
  674.     {
  675.         GFree(hdib);
  676.         hdib = NULL;
  677.         goto exit;
  678.     }
  679.  
  680.     /*
  681.      *  call GetDIBits with a NON-NULL lpBits param, and actualy get the
  682.      *  bits this time
  683.      */
  684.     lpbi = GLock(hdib);
  685.  
  686.     GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
  687.         (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi),
  688.         (LPBITMAPINFO)lpbi, wUsage);
  689.  
  690.     bi = *lpbi;
  691.     GUnlock(hdib);
  692.  
  693. exit:
  694.     SelectPalette(hdc,hpal,FALSE);
  695.     DeleteDC(hdc);
  696.     return hdib;
  697. }
  698.  
  699. /*
  700.  *  BitmapFromDib()
  701.  *
  702.  *  Will create a DDB (Device Dependent Bitmap) given a global handle to
  703.  *  a memory block in CF_DIB format
  704.  *
  705.  */
  706. HBITMAP BitmapFromDib(HANDLE hdib, HPALETTE hpal, WORD wUsage)
  707. {
  708.     LPBITMAPINFOHEADER lpbi;
  709.     HPALETTE    hpalT;
  710.     HDC         hdc;
  711.     HBITMAP     hbm;
  712.  
  713.     if (!hdib)
  714.         return NULL;
  715.  
  716.     if (wUsage == 0)
  717.         wUsage = DIB_RGB_COLORS;
  718.  
  719.     lpbi = GLock(hdib);
  720.  
  721.     if (!lpbi)
  722.         return NULL;
  723.  
  724.     hdc = GetDC(NULL);
  725. //  hdc = CreateCompatibleDC(NULL);
  726.  
  727.     if (hpal)
  728.     {
  729.         hpalT = SelectPalette(hdc,hpal,FALSE);
  730.         RealizePalette(hdc);  // why is this needed on a MEMORY DC? GDI bug??
  731.     }
  732.  
  733. #if 0
  734.     if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  735.     {
  736.         dx   = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  737.         dy   = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  738.         bits = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
  739.     }
  740.     else
  741.     {
  742.         dx   = (WORD)lpbi->biWidth;
  743.         dy   = (WORD)lpbi->biHeight;
  744.         bits = (WORD)lpbi->biBitCount;
  745.     }
  746.  
  747.     if (bMonoBitmap /* || bits == 1 */)
  748.     {
  749.         hbm = CreateBitmap(dx,dy,1,1,NULL);
  750.     }
  751.     else
  752.     {
  753.         HDC hdcScreen = GetDC(NULL);
  754.         hbm = CreateCompatibleBitmap(hdcScreen,dx,dy);
  755.         ReleaseDC(NULL,hdcScreen);
  756.     }
  757.  
  758.     if (hbm)
  759.     {
  760.         if (fErrProp)
  761.             SetDIBitsErrProp(hdc,hbm,0,dy,
  762.                (LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
  763.                (LPBITMAPINFO)lpbi,wUsage);
  764.         else
  765.             SetDIBits(hdc,hbm,0,dy,
  766.                (LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
  767.                (LPBITMAPINFO)lpbi,wUsage);
  768.     }
  769.  
  770. #else
  771.     hbm = CreateDIBitmap(hdc,
  772.                 (LPBITMAPINFOHEADER)lpbi,
  773.                 (LONG)CBM_INIT,
  774.                 (LPSTR)lpbi + (int)lpbi->biSize + PaletteSize(lpbi),
  775.                 (LPBITMAPINFO)lpbi,
  776.                 wUsage );
  777. #endif
  778.  
  779.     if (hpal && hpalT)
  780.         SelectPalette(hdc,hpalT,FALSE);
  781.  
  782. //  DeleteDC(hdc);
  783.     ReleaseDC(NULL,hdc);
  784.  
  785.     GUnlock(hdib);
  786.     return hbm;
  787. }
  788.  
  789. /*
  790.  *  DibFromDib()
  791.  *
  792.  *  Will convert a DIB in 1 format to a DIB in the specifed format
  793.  *
  794.  */
  795. HANDLE DibFromDib(HANDLE hdib, DWORD biStyle, WORD biBits, HPALETTE hpal, WORD wUsage)
  796. {
  797.     BITMAPINFOHEADER bi;
  798.     HBITMAP     hbm;
  799.     BOOL        fKillPalette=FALSE;
  800.  
  801.     if (!hdib)
  802.         return NULL;
  803.  
  804.     DibInfo(hdib,&bi);
  805.  
  806.     /*
  807.      *  do we have the requested format already?
  808.      */
  809.     if (bi.biCompression == biStyle && bi.biBitCount == biBits)
  810.         return hdib;
  811.  
  812.     if (hpal == NULL)
  813.     {
  814.         hpal = CreateDibPalette(hdib);
  815.         fKillPalette++;
  816.     }
  817.  
  818.     hbm = BitmapFromDib(hdib,hpal,wUsage);
  819.  
  820.     if (hbm == NULL)
  821.     {
  822.         hdib = NULL;
  823.     }
  824.     else
  825.     {
  826.         hdib = DibFromBitmap(hbm,biStyle,biBits,hpal,wUsage);
  827.         DeleteObject(hbm);
  828.     }
  829.  
  830.     if (fKillPalette && hpal)
  831.         DeleteObject(hpal);
  832.  
  833.     return hdib;
  834. }
  835.  
  836. /*
  837.  *  CreateLogicalDib
  838.  *
  839.  *  Given a DDB and a HPALETTE create a "logical" DIB
  840.  *
  841.  *  if the HBITMAP is NULL create a DIB from the system "stock" bitmap
  842.  *      This is used to save a logical palette to a disk file as a DIB
  843.  *
  844.  *  if the HPALETTE is NULL use the system "stock" palette (ie the
  845.  *      system palette)
  846.  *
  847.  *  a "logical" DIB is a DIB where the DIB color table *exactly* matches
  848.  *  the passed logical palette.  There will be no system colors in the DIB
  849.  *  block, and a pixel value of <n> in the DIB will correspond to logical
  850.  *  palette index <n>.
  851.  *
  852.  *  This is accomplished by doing a GetDIBits() with the DIB_PAL_COLORS
  853.  *  option then converting the palindexes returned in the color table
  854.  *  from palette indexes to logical RGB values.  The entire passed logical
  855.  *  palette is always copied to the DIB color table.
  856.  *
  857.  *  The DIB color table will have exactly the same number of entries as
  858.  *  the logical palette.  Normaly GetDIBits() will always set biClrUsed to
  859.  *  the maximum colors supported by the device regardless of the number of
  860.  *  colors in the logical palette
  861.  *
  862.  *  Why would you want to do this?  The major reason for a "logical" DIB
  863.  *  is so when the DIB is written to a disk file then reloaded the logical
  864.  *  palette created from the DIB color table will be the same as one used
  865.  *  originaly to create the bitmap.  It also will prevent GDI from doing
  866.  *  nearest color matching on PC_RESERVED palettes.
  867.  *
  868.  *  ** What do we do if the logical palette has more than 256 entries!!!!!
  869.  *  ** GetDIBits() may return logical palette index's that are greater than
  870.  *  ** 256, we cant represent these colors in the "logical" DIB
  871.  *  **
  872.  *  ** for now hose the caller?????
  873.  *
  874.  */
  875.  
  876. HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal)
  877. {
  878.     BITMAP              bm;
  879.     BITMAPINFOHEADER    bi;
  880.     LPBITMAPINFOHEADER  lpDib;      // pointer to DIB
  881.     LPBITMAPINFOHEADER  lpbi;       // temp pointer to BITMAPINFO
  882.     DWORD               dwLen;
  883.     DWORD               dw;
  884.     int                 n;
  885.     int                 nColors;
  886.     HANDLE              hdib;
  887.     HDC                 hdc;
  888.     BYTE FAR *          lpBits;
  889.     WORD FAR *          lpCT;
  890.     RGBQUAD FAR *       lpRgb;
  891.     PALETTEENTRY        peT;
  892.     HPALETTE            hpalT;
  893.  
  894.     if (hpal == NULL)
  895.         hpal = GetStockObject(DEFAULT_PALETTE);
  896.  
  897.     if (hbm == NULL)
  898.         hbm = NULL; // ????GetStockObject(STOCK_BITMAP);
  899.  
  900.     GetObject(hpal,sizeof(nColors),(LPSTR)&nColors);
  901.     GetObject(hbm,sizeof(bm),(LPSTR)&bm);
  902.  
  903.     if (biBits == 0)
  904.         biBits = nColors > 16 ? 8 : 4;
  905.  
  906.     if (nColors > 256)      // ACK!
  907.         ;                   // How do we handle this????
  908.  
  909.     bi.biSize               = sizeof(BITMAPINFOHEADER);
  910.     bi.biWidth              = bm.bmWidth;
  911.     bi.biHeight             = bm.bmHeight;
  912.     bi.biPlanes             = 1;
  913.     bi.biBitCount           = biBits;
  914.     bi.biCompression        = BI_RGB;
  915.     bi.biSizeImage          = (DWORD)WIDTHBYTES(bm.bmWidth * biBits) * bm.bmHeight;
  916.     bi.biXPelsPerMeter      = 0;
  917.     bi.biYPelsPerMeter      = 0;
  918.     bi.biClrUsed            = nColors;
  919.     bi.biClrImportant       = 0;
  920.  
  921.     dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  922.  
  923.     hdib = GAlloc(dwLen);
  924.  
  925.     if (!hdib)
  926.         return NULL;
  927.  
  928.     lpbi = GAllocPtr(bi.biSize + 256 * sizeof(RGBQUAD));
  929.  
  930.     if (!lpbi)
  931.     {
  932.         GFree(hdib);
  933.         return NULL;
  934.     }
  935.  
  936.     hdc = GetDC(NULL);
  937.     hpalT = SelectPalette(hdc,hpal,FALSE);
  938.     RealizePalette(hdc);  // why is this needed on a MEMORY DC? GDI bug??
  939.  
  940.     lpDib = GLock(hdib);
  941.  
  942.     *lpbi  = bi;
  943.     *lpDib = bi;
  944.     lpCT   = (WORD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  945.     lpRgb  = (RGBQUAD FAR *)((LPSTR)lpDib + (WORD)lpDib->biSize);
  946.     lpBits = (LPSTR)lpDib + (WORD)lpDib->biSize + PaletteSize(lpDib);
  947.  
  948.     /*
  949.      *  call GetDIBits to get the DIB bits and fill the color table with
  950.      *  logical palette index's
  951.      */
  952.     GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
  953.         lpBits,(LPBITMAPINFO)lpbi, DIB_PAL_COLORS);
  954.  
  955.     /*
  956.      *  Now convert the DIB bits into "real" logical palette index's
  957.      *
  958.      *  lpCT        points to the DIB color table wich is a WORD array of
  959.      *              logical palette index's
  960.      *
  961.      *  lpBits      points to the DIB bits, each DIB pixel is a index into
  962.      *              the DIB color table.
  963.      *
  964.      */
  965.  
  966.     if (biBits == 8)
  967.     {
  968.         for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpBits)++)
  969.             *lpBits = (BYTE)lpCT[*lpBits];
  970.     }
  971.     else // biBits == 4
  972.     {
  973.         for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpBits)++)
  974.             *lpBits = lpCT[*lpBits & 0x0F] | (lpCT[(*lpBits >> 4) & 0x0F] << 4);
  975.     }
  976.  
  977.     /*
  978.      *  Now copy the RGBs in the logical palette to the dib color table
  979.      */
  980.     for (n=0; n<nColors; n++,lpRgb++)
  981.     {
  982.         GetPaletteEntries(hpal,n,1,&peT);
  983.  
  984.         lpRgb->rgbRed      = peT.peRed;
  985.         lpRgb->rgbGreen    = peT.peGreen;
  986.         lpRgb->rgbBlue     = peT.peBlue;
  987.         lpRgb->rgbReserved = (BYTE)0;
  988.     }
  989.  
  990.     GUnlock(hdib);
  991.     GFreePtr(lpbi);
  992.  
  993.     SelectPalette(hdc,hpalT,FALSE);
  994.     ReleaseDC(NULL,hdc);
  995.  
  996.     return hdib;
  997. }
  998.  
  999. void xlatClut8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  1000. {
  1001.     DWORD dw;
  1002.  
  1003.     for (dw = 0; dw < dwSize; dw++, ((BYTE huge *)pb)++)
  1004.         *pb = xlat[*pb];
  1005. }
  1006.  
  1007. void xlatClut4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  1008. {
  1009.     DWORD dw;
  1010.  
  1011.     for (dw = 0; dw < dwSize; dw++, ((BYTE huge *)pb)++)
  1012.         *pb = xlat[*pb & 0x0F] | (xlat[(*pb >> 4) & 0x0F] << 4);
  1013. }
  1014.  
  1015. #define RLE_ESCAPE  0
  1016. #define RLE_EOL     0
  1017. #define RLE_EOF     1
  1018. #define RLE_JMP     2
  1019.  
  1020. void xlatRle8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  1021. {
  1022.     BYTE    cnt;
  1023.     BYTE    b;
  1024.     BYTE huge *prle = pb;
  1025.  
  1026.     for(;;)
  1027.     {
  1028.         cnt = *prle++;
  1029.         b   = *prle;
  1030.  
  1031.         if (cnt == RLE_ESCAPE)
  1032.         {
  1033.             prle++;
  1034.  
  1035.             switch (b)
  1036.             {
  1037.                 case RLE_EOF:
  1038.                     return;
  1039.  
  1040.                 case RLE_EOL:
  1041.                     break;
  1042.  
  1043.                 case RLE_JMP:
  1044.                     prle++;     // skip dX
  1045.                     prle++;     // skip dY
  1046.                     break;
  1047.  
  1048.                 default:
  1049.                     cnt = b;
  1050.                     for (b=0; b<cnt; b++,prle++)
  1051.                         *prle = xlat[*prle];
  1052.  
  1053.                     if (cnt & 1)
  1054.                         prle++;
  1055.  
  1056.                     break;
  1057.             }
  1058.         }
  1059.         else
  1060.         {
  1061.             *prle++ = xlat[b];
  1062.         }
  1063.     }
  1064. }
  1065.  
  1066. void xlatRle4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  1067. {
  1068. }
  1069.  
  1070. //
  1071. // MapDib - map the given DIB so it matches the specifed palette
  1072. //
  1073. BOOL MapDib(HANDLE hdib, HPALETTE hpal)
  1074. {
  1075.     LPBITMAPINFOHEADER  lpbi;
  1076.     PALETTEENTRY        pe;
  1077.     int                 n;
  1078.     int                 nDibColors;
  1079.     int                 nPalColors;
  1080.     BYTE FAR *          lpBits;
  1081.     RGBQUAD FAR *       lpRgb;
  1082.     BYTE                xlat[256];
  1083.     DWORD               dwSize;
  1084.  
  1085.     if (!hpal || !hdib)
  1086.         return FALSE;
  1087.  
  1088.     lpbi   = GLock(hdib);
  1089.     lpRgb  = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  1090.     lpBits = DibXY(lpbi,0,0);
  1091.  
  1092.     GetObject(hpal,sizeof(int),(LPSTR)&nPalColors);
  1093.     nDibColors = DibNumColors(lpbi);
  1094.  
  1095.     if (nPalColors > nDibColors)
  1096.     {
  1097.         //
  1098.         // This is bad, we need to grow the dib!  punt for now
  1099.         //
  1100.         nPalColors = nDibColors;
  1101.     }
  1102.  
  1103.     //
  1104.     //  build a xlat table. from the current DIB colors to the given
  1105.     //  palette.
  1106.     //
  1107.     for (n=0; n<nDibColors; n++)
  1108.         xlat[n] = (BYTE)GetNearestPaletteIndex(hpal,RGB(lpRgb[n].rgbRed,lpRgb[n].rgbGreen,lpRgb[n].rgbBlue));
  1109.  
  1110.     //
  1111.     // translate the DIB bits
  1112.     //
  1113.     if ((dwSize = lpbi->biSizeImage) == 0)
  1114.         dwSize = lpbi->biHeight * DIBWIDTHBYTES(*lpbi);
  1115.  
  1116.     switch ((WORD)lpbi->biCompression)
  1117.     {
  1118.         case BI_RLE8:
  1119.             xlatRle8(lpBits, dwSize, xlat);
  1120.             break;
  1121.  
  1122.         case BI_RLE4:
  1123.             xlatRle4(lpBits, dwSize, xlat);
  1124.             break;
  1125.  
  1126.         case BI_RGB:
  1127.             if (lpbi->biBitCount == 8)
  1128.                 xlatClut8(lpBits, dwSize, xlat);
  1129.             else
  1130.                 xlatClut4(lpBits, dwSize, xlat);
  1131.             break;
  1132.     }
  1133.  
  1134.     //
  1135.     //  Now copy the RGBs in the logical palette to the dib color table
  1136.     //
  1137.     for (n=0; n<nPalColors; n++)
  1138.     {
  1139.         GetPaletteEntries(hpal,n,1,&pe);
  1140.  
  1141.         lpRgb[n].rgbRed      = pe.peRed;
  1142.         lpRgb[n].rgbGreen    = pe.peGreen;
  1143.         lpRgb[n].rgbBlue     = pe.peBlue;
  1144.         lpRgb[n].rgbReserved = (BYTE)0;
  1145.     }
  1146.  
  1147.     for (n=nPalColors; n<nDibColors; n++)
  1148.     {
  1149.         lpRgb[n].rgbRed      = (BYTE)0;
  1150.         lpRgb[n].rgbGreen    = (BYTE)0;
  1151.         lpRgb[n].rgbBlue     = (BYTE)0;
  1152.         lpRgb[n].rgbReserved = (BYTE)0;
  1153.     }
  1154.  
  1155.     GUnlock(hdib);
  1156.     return TRUE;
  1157. }
  1158.  
  1159.  
  1160. /*
  1161.  *  Draws bitmap <hbm> at the specifed position in DC <hdc>
  1162.  *
  1163.  */
  1164. BOOL StretchBitmap(HDC hdc, int x, int y, int dx, int dy, HBITMAP hbm, int x0, int y0, int dx0, int dy0, DWORD rop)
  1165. {
  1166.     HDC hdcBits;
  1167.  
  1168.     HPALETTE hpal, hpalT;
  1169.     BOOL f;
  1170.  
  1171.     if (!hdc || !hbm)
  1172.         return FALSE;
  1173.  
  1174.     hpal = SelectPalette(hdc,GetStockObject(DEFAULT_PALETTE),FALSE);
  1175.     SelectPalette(hdc,hpal,FALSE);
  1176.  
  1177.     hdcBits = CreateCompatibleDC(hdc);
  1178.     SelectObject(hdcBits,hbm);
  1179.     hpalT = SelectPalette(hdcBits,hpal,FALSE);
  1180.     RealizePalette(hdcBits);
  1181.     f = StretchBlt(hdc,x,y,dx,dy,hdcBits,x0,y0,dx0,dy0,rop);
  1182.     SelectPalette(hdcBits,hpalT,FALSE);
  1183.     DeleteDC(hdcBits);
  1184.  
  1185.     return f;
  1186. }
  1187.  
  1188. /*
  1189.  *  Draws bitmap <hbm> at the specifed position in DC <hdc>
  1190.  *
  1191.  */
  1192. BOOL DrawBitmap(HDC hdc, int x, int y, HBITMAP hbm, DWORD rop)
  1193. {
  1194.     HDC hdcBits;
  1195.     BITMAP bm;
  1196.     BOOL f;
  1197.  
  1198.     if (!hdc || !hbm)
  1199.         return FALSE;
  1200.  
  1201.     hdcBits = CreateCompatibleDC(hdc);
  1202.     GetObject(hbm,sizeof(BITMAP),(LPSTR)&bm);
  1203.     SelectObject(hdcBits,hbm);
  1204.     f = BitBlt(hdc,x,y,bm.bmWidth,bm.bmHeight,hdcBits,0,0,rop);
  1205.     DeleteDC(hdcBits);
  1206.  
  1207.     return f;
  1208. }
  1209.  
  1210. /*
  1211.  *  Draws HDIB <hdib> at the specifed position in DC <hdc>
  1212.  *
  1213.  */
  1214. BOOL DrawDib(HDC hdc, int x, int y, HANDLE hdib, HPALETTE hpal, WORD wUsage)
  1215. {
  1216.     HPALETTE hpalT;
  1217.  
  1218.     if (hpal)
  1219.     {
  1220.         hpalT = SelectPalette(hdc,hpal,FALSE);
  1221.         RealizePalette(hdc);
  1222.     }
  1223.  
  1224.     DibBlt(hdc,x,y,-1,-1,hdib,0,0,SRCCOPY,wUsage);
  1225.  
  1226.     if (hpal)
  1227.     {
  1228.         SelectPalette(hdc,hpalT,FALSE);
  1229.     }
  1230.     return TRUE;
  1231. }
  1232.  
  1233.  
  1234. /*
  1235.  *  SetDibUsage(hdib,hpal,wUsage)
  1236.  *
  1237.  *  Modifies the color table of the passed DIB for use with the wUsage
  1238.  *  parameter specifed.
  1239.  *
  1240.  *  if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
  1241.  *  if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
  1242.  *      in the passed palette
  1243.  *
  1244.  */
  1245. BOOL SetDibUsage(HANDLE hdib, HPALETTE hpal,WORD wUsage)
  1246. {
  1247.     LPBITMAPINFOHEADER lpbi;
  1248.     PALETTEENTRY       ape[MAXPALETTE];
  1249.     RGBQUAD FAR *      pRgb;
  1250.     WORD FAR *         pw;
  1251.     int                nColors;
  1252.     int                n;
  1253.  
  1254.     if (hpal == NULL)
  1255.         hpal = GetStockObject(DEFAULT_PALETTE);
  1256.  
  1257.     if (!hdib)
  1258.         return FALSE;
  1259.  
  1260.     lpbi = GLock(hdib);
  1261.  
  1262.     if (!lpbi)
  1263.         return FALSE;
  1264.  
  1265.     nColors = DibNumColors(lpbi);
  1266.  
  1267.     if (nColors > 0)
  1268.     {
  1269.         pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  1270.  
  1271.         switch (wUsage)
  1272.         {
  1273.             //
  1274.             // Set the DIB color table to palette indexes
  1275.             //
  1276.             case DIB_PAL_COLORS:
  1277.                 for (pw = (WORD FAR*)pRgb,n=0; n<nColors; n++,pw++)
  1278.                     *pw = n;
  1279.                 break;
  1280.  
  1281.             //
  1282.             // Set the DIB color table to RGBQUADS
  1283.             //
  1284.             default:
  1285.             case DIB_RGB_COLORS:
  1286.                 nColors = min(nColors,MAXPALETTE);
  1287.  
  1288.                 GetPaletteEntries(hpal,0,nColors,ape);
  1289.  
  1290.                 for (n=0; n<nColors; n++)
  1291.                 {
  1292.                     pRgb[n].rgbRed      = ape[n].peRed;
  1293.                     pRgb[n].rgbGreen    = ape[n].peGreen;
  1294.                     pRgb[n].rgbBlue     = ape[n].peBlue;
  1295.                     pRgb[n].rgbReserved = 0;
  1296.                 }
  1297.                 break;
  1298.         }
  1299.     }
  1300.     GUnlock(hdib);
  1301.     return TRUE;
  1302. }
  1303.  
  1304. /*
  1305.  *  SetPalFlags(hpal,iIndex, cnt, wFlags)
  1306.  *
  1307.  *  Modifies the palette flags of all indexs in the range (iIndex - nIndex+cnt)
  1308.  *  to the parameter specifed.
  1309.  *
  1310.  */
  1311. BOOL SetPalFlags(HPALETTE hpal, int iIndex, int cntEntries, WORD wFlags)
  1312. {
  1313.     int     i;
  1314.     BOOL    f;
  1315.     PALETTEENTRY FAR *lppe;
  1316.  
  1317.     if (hpal == NULL)
  1318.         return FALSE;
  1319.  
  1320.     if (cntEntries < 0)
  1321.         GetObject(hpal,sizeof(int),(LPSTR)&cntEntries);
  1322.  
  1323.     lppe = GAllocPtr((LONG)cntEntries * sizeof(PALETTEENTRY));
  1324.  
  1325.     if (!lppe)
  1326.         return FALSE;
  1327.  
  1328.     GetPaletteEntries(hpal, iIndex, cntEntries, lppe);
  1329.  
  1330.     for (i=0; i<cntEntries; i++)
  1331.     {
  1332.         lppe[i].peFlags = (BYTE)wFlags;
  1333.     }
  1334.  
  1335.     f = SetPaletteEntries(hpal, iIndex, cntEntries, lppe);
  1336.  
  1337.     GFreePtr(lppe);
  1338.     return f;
  1339. }
  1340.  
  1341. /*
  1342.  *  PalEq(hpal1,hpal2)
  1343.  *
  1344.  *  return TRUE if the palette's are the same
  1345.  *
  1346.  */
  1347. BOOL PalEq(HPALETTE hpal1, HPALETTE hpal2)
  1348. {
  1349.     BOOL    f;
  1350.     int     i;
  1351.     int     nPal1,nPal2;
  1352.     PALETTEENTRY FAR *ppe;
  1353.  
  1354.     if (hpal1 == hpal2)
  1355.         return TRUE;
  1356.  
  1357.     if (!hpal1 || !hpal2)
  1358.         return FALSE;
  1359.  
  1360.     GetObject(hpal1,sizeof(int),(LPSTR)&nPal1);
  1361.     GetObject(hpal2,sizeof(int),(LPSTR)&nPal2);
  1362.  
  1363.     if (nPal1 != nPal2)
  1364.         return FALSE;
  1365.  
  1366.     ppe = GAllocPtr(nPal1 * 2 * sizeof(PALETTEENTRY));
  1367.  
  1368.     if (!ppe)
  1369.         return FALSE;
  1370.  
  1371.     GetPaletteEntries(hpal1, 0, nPal1, ppe);
  1372.     GetPaletteEntries(hpal2, 0, nPal2, ppe+nPal1);
  1373.  
  1374.     for (f=TRUE,i=0; f && i<nPal1; i++)
  1375.     {
  1376.         f &= (ppe[i].peRed   == ppe[i+nPal1].peRed   &&
  1377.               ppe[i].peBlue  == ppe[i+nPal1].peBlue  &&
  1378.               ppe[i].peGreen == ppe[i+nPal1].peGreen);
  1379.     }
  1380.  
  1381.     GFreePtr(ppe);
  1382.     return f;
  1383. }
  1384.  
  1385. /*
  1386.  *  StretchDibBlt()
  1387.  *
  1388.  *  draws a bitmap in CF_DIB format, using StretchDIBits()
  1389.  *
  1390.  *  takes the same parameters as StretchBlt()
  1391.  */
  1392. BOOL StretchDibBlt(HDC hdc, int x, int y, int dx, int dy, HANDLE hdib, int x0, int y0, int dx0, int dy0, LONG rop, WORD wUsage)
  1393. {
  1394.     LPBITMAPINFOHEADER lpbi;
  1395.     LPSTR        pBuf;
  1396.     BOOL         f;
  1397.  
  1398.     if (!hdib)
  1399.         return PatBlt(hdc,x,y,dx,dy,rop);
  1400.  
  1401.     if (wUsage == 0)
  1402.         wUsage = DIB_RGB_COLORS;
  1403.  
  1404.     lpbi = GLock(hdib);
  1405.  
  1406.     if (!lpbi)
  1407.         return FALSE;
  1408.  
  1409.     if (dx0 == -1 && dy0 == -1)
  1410.     {
  1411.         if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  1412.         {
  1413.             dx0 = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  1414.             dy0 = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  1415.         }
  1416.         else
  1417.         {
  1418.             dx0 = (int)lpbi->biWidth;
  1419.             dy0 = (int)lpbi->biHeight;
  1420.         }
  1421.     }
  1422.  
  1423.     if (dx < 0 && dy < 0)
  1424.     {
  1425.         dx = dx0 * -dx;
  1426.         dy = dy0 * -dy;
  1427.     }
  1428.  
  1429.     pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  1430.  
  1431.     f = StretchDIBits (
  1432.         hdc,
  1433.         x,y,
  1434.         dx,dy,
  1435.         x0,y0,
  1436.         dx0,dy0,
  1437.         pBuf, (LPBITMAPINFO)lpbi,
  1438.         wUsage,
  1439.         rop);
  1440.  
  1441.     GUnlock(hdib);
  1442.     return f;
  1443. }
  1444.  
  1445. /*
  1446.  *  DibBlt()
  1447.  *
  1448.  *  draws a bitmap in CF_DIB format, using SetDIBits to device.
  1449.  *
  1450.  *  takes the same parameters as BitBlt()
  1451.  */
  1452. BOOL DibBlt(HDC hdc, int x0, int y0, int dx, int dy, HANDLE hdib, int x1, int y1, LONG rop, WORD wUsage)
  1453. {
  1454.     LPBITMAPINFOHEADER lpbi;
  1455.     LPSTR       pBuf;
  1456.     BOOL        f;
  1457.  
  1458.     if (!hdib)
  1459.         return PatBlt(hdc,x0,y0,dx,dy,rop);
  1460.  
  1461.     if (wUsage == 0)
  1462.         wUsage = DIB_RGB_COLORS;
  1463.  
  1464.     lpbi = GLock(hdib);
  1465.  
  1466.     if (!lpbi)
  1467.         return FALSE;
  1468.  
  1469.     if (dx == -1 && dy == -1)
  1470.     {
  1471.         if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  1472.         {
  1473.             dx = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  1474.             dy = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  1475.         }
  1476.         else
  1477.         {
  1478.             dx = (int)lpbi->biWidth;
  1479.             dy = (int)lpbi->biHeight;
  1480.         }
  1481.     }
  1482.  
  1483.     pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  1484.  
  1485. #if 0
  1486.     f = SetDIBitsToDevice(hdc, x0, y0, dx, dy,
  1487.         x1,y1,
  1488.         x1,
  1489.         dy,
  1490.         pBuf, (LPBITMAPINFO)lpbi,
  1491.         wUsage );
  1492. #else
  1493.     f = StretchDIBits (
  1494.         hdc,
  1495.         x0,y0,
  1496.         dx,dy,
  1497.         x1,y1,
  1498.         dx,dy,
  1499.         pBuf, (LPBITMAPINFO)lpbi,
  1500.         wUsage,
  1501.         rop);
  1502. #endif
  1503.  
  1504.     GUnlock(hdib);
  1505.     return f;
  1506. }
  1507.  
  1508. LPVOID DibLock(HANDLE hdib,int x, int y)
  1509. {
  1510.     return DibXY((LPBITMAPINFOHEADER)GLock(hdib),x,y);
  1511. }
  1512.  
  1513. VOID DibUnlock(HANDLE hdib)
  1514. {
  1515.     GUnlock(hdib);
  1516. }
  1517.  
  1518. LPVOID DibXY(LPBITMAPINFOHEADER lpbi,int x, int y)
  1519. {
  1520.     BYTE huge *pBits;
  1521.     DWORD ulWidthBytes;
  1522.  
  1523.     pBits = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  1524.  
  1525.     ulWidthBytes = DIBWIDTHBYTES(*lpbi);
  1526.  
  1527.     pBits += (ulWidthBytes * (long)y) + (x * (int)lpbi->biBitCount / 8);
  1528.  
  1529.     return (LPVOID)pBits;
  1530. }
  1531.  
  1532. HANDLE CreateDib(int bits, int dx, int dy)
  1533. {
  1534.     HANDLE              hdib;
  1535.     BITMAPINFOHEADER    bi;
  1536.     LPBITMAPINFOHEADER  lpbi;
  1537.     DWORD FAR *         pRgb;
  1538.     WORD                i;
  1539.  
  1540.     //
  1541.     // These are the standard VGA colors, we will be stuck with until the
  1542.     // end of time!
  1543.     //
  1544.     static DWORD CosmicColors[16] = {
  1545.          0x00000000        // 0000  black
  1546.         ,0x00800000        // 0001  dark red
  1547.         ,0x00008000        // 0010  dark green
  1548.         ,0x00808000        // 0011  mustard
  1549.         ,0x00000080        // 0100  dark blue
  1550.         ,0x00800080        // 0101  purple
  1551.         ,0x00008080        // 0110  dark turquoise
  1552.         ,0x00C0C0C0        // 1000  gray
  1553.         ,0x00808080        // 0111  dark gray
  1554.         ,0x00FF0000        // 1001  red
  1555.         ,0x0000FF00        // 1010  green
  1556.         ,0x00FFFF00        // 1011  yellow
  1557.         ,0x000000FF        // 1100  blue
  1558.         ,0x00FF00FF        // 1101  pink (magenta)
  1559.         ,0x0000FFFF        // 1110  cyan
  1560.         ,0x00FFFFFF        // 1111  white
  1561.         };
  1562.  
  1563.     if (bits <= 0)
  1564.         bits = 8;
  1565.  
  1566.     bi.biSize           = sizeof(BITMAPINFOHEADER);
  1567.     bi.biPlanes         = 1;
  1568.     bi.biBitCount       = bits;
  1569.     bi.biWidth          = dx;
  1570.     bi.biHeight         = dy;
  1571.     bi.biCompression    = BI_RGB;
  1572.     bi.biSizeImage      = (long) dy * DIBWIDTHBYTES(bi);
  1573.     bi.biXPelsPerMeter  = 0;
  1574.     bi.biYPelsPerMeter  = 0;
  1575.     bi.biClrUsed    = 0;
  1576.     bi.biClrImportant   = 0;
  1577.     bi.biClrUsed    = DibNumColors(&bi);
  1578.  
  1579.     hdib = GAllocF(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(BITMAPINFOHEADER)
  1580.         + (long)bi.biClrUsed * sizeof(RGBQUAD)
  1581.         + (long)dy * DIBWIDTHBYTES(bi));
  1582.  
  1583.     if (hdib)
  1584.     {
  1585.         lpbi  = GLock(hdib);
  1586.         *lpbi = bi;
  1587.  
  1588.         pRgb  = (LPVOID)((LPSTR)lpbi + (int)lpbi->biSize);
  1589.  
  1590.         //
  1591.         //  setup the color table
  1592.         //
  1593.         if (bits == 1)
  1594.         {
  1595.             pRgb[0] = CosmicColors[0];
  1596.             pRgb[1] = CosmicColors[15];
  1597.         }
  1598.         else
  1599.         {
  1600.             for (i=0; i<bi.biClrUsed; i++)
  1601.                 pRgb[i] = CosmicColors[i % 16];
  1602.         }
  1603.  
  1604.         GUnlock(hdib);
  1605.     }
  1606.  
  1607.     return hdib;
  1608. }
  1609.  
  1610. HANDLE CopyDib (HANDLE hdib)
  1611. {
  1612.     BYTE huge *ps;
  1613.     BYTE huge *pd;
  1614.     HANDLE h;
  1615.     DWORD cnt;
  1616.  
  1617.     if (h = GAlloc(cnt = GSize(hdib)))
  1618.     {
  1619.         ps = GLock(hdib);
  1620.         pd = GLock(h);
  1621.     hmemcpy(pd, ps, cnt);
  1622.  
  1623.         GUnlock(hdib);
  1624.         GUnlock(h);
  1625.     }
  1626.     return h;
  1627. }
  1628.